package com.wsfPro.util.mail;

import freemarker.template.Template;
import freemarker.template.TemplateException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.AsyncResult;
import org.springframework.stereotype.Component;
import org.springframework.ui.freemarker.FreeMarkerTemplateUtils;
import org.springframework.web.servlet.view.freemarker.FreeMarkerConfigurer;

import javax.activation.DataHandler;
import javax.activation.FileDataSource;
import javax.mail.*;
import javax.mail.Message.RecipientType;
import javax.mail.internet.*;
import java.io.*;
import java.util.*;
import java.util.concurrent.Future;

// main，启动项目单线程跑可以正常运行，多线程异步跑不起来
// 使用单例即可，因为发送方为固定不变session
@Component
public class MailSendUtil {
  @Autowired private MailSender mailSender;
  @Autowired private JavaMailSender javaMailSender;
  @Autowired private FreeMarkerConfigurer freeMarkerConfigurer;
  private Logger log = LoggerFactory.getLogger(MailSendUtil.class);

  @Async
  public Future<Boolean> sendMail(String to, String subject, String content) {
    Boolean flag = true;
    try {
      SimpleMailMessage message = new SimpleMailMessage();
      message.setTo(to);
      message.setSubject(subject);
      message.setText(content);
      message.setFrom(mailSender.getForm());
      javaMailSender.send(message);
    } catch (Exception e) {
      flag = false;
    }
    return new AsyncResult<>(flag);
  }

  @Async
  public Future<Boolean> sendMail(MailRecipient info) {
    Boolean flag = true;
    try {
      MimeMessage message = javaMailSender.createMimeMessage();
      MimeMessageHelper helper = new MimeMessageHelper(message, true);
      helper.setFrom(mailSender.getForm());
      helper.setTo(info.getToAddress());
      if (info.getBcc() != null) {
        helper.setBcc(info.getBcc());
      }
      if (info.getCc() != null) {
        helper.setCc(info.getCc());
      }
      helper.setSubject(info.getSubject());
      helper.setText(info.getContent(), true);
      if (info.getContentImage() != null) {
        helper.addInline(info.getContentImageID(), info.getContentImage());
      }
      if (info.getMailAttachments() != null && info.getMailAttachments().length > 0) {
        for (File mailAttachment : info.getMailAttachments()) {
          helper.addAttachment(mailAttachment.getName(), mailAttachment);
        }
      }
      javaMailSender.send(message);
    } catch (Exception e) {
      flag = false;
    }
    return new AsyncResult<>(flag);
  }

  public String readTemplate(Object params, String templateName) {
    Map<String, Object> model = new HashMap<>();
    model.put("params", params);
    String content = null;
    Template template = null;
    try {
      template = freeMarkerConfigurer.getConfiguration().getTemplate(templateName);
      content = FreeMarkerTemplateUtils.processTemplateIntoString(template, model);
    } catch (IOException e) {
      e.printStackTrace();
    } catch (TemplateException e) {
      e.printStackTrace();
    }
    return content;
  }

  public Message setMessageInfo(MailRecipient info) throws Exception {

    final Properties p = new Properties();
    p.setProperty("mail.smtp.host", mailSender.getHost());
    p.setProperty("mail.smtp.auth", mailSender.getAuth());
    p.setProperty("mail.smtp.user", mailSender.getForm());
    p.setProperty("mail.smtp.pass", mailSender.getFormPassword());
    p.setProperty("mail.debug", mailSender.getDebug());

    Message message =
        new MimeMessage(
            Session.getInstance(
                p,
                new Authenticator() {
                  @Override
                  protected PasswordAuthentication getPasswordAuthentication() {
                    return new PasswordAuthentication(
                        p.getProperty("mail.smtp.user"), p.getProperty("mail.smtp.pass"));
                  }
                }));

    message.setReplyTo(InternetAddress.parse(mailSender.getReplayAddress()));
    message.setFrom(new InternetAddress(p.getProperty("mail.smtp.user"), "WSF"));
    message.setSubject(info.getSubject());
    message.setRecipient(RecipientType.TO, new InternetAddress(info.getToAddress()));
    // 创建邮件的各个 MimeBodyPart 部分
    // 将邮件中各个部分组合到一个"mixed"型的 MimeMultipart 对象
    MimeMultipart allPart = new MimeMultipart("mixed");
    if (info.getMailAttachments() != null && info.getMailAttachments().length > 0) {
      for (File file : info.getMailAttachments()) {
        allPart.addBodyPart(createAttachment(file));
      }
    }

    MimeBodyPart content = createContent(info);
    allPart.addBodyPart(content);

    // 将上面混合型的 MimeMultipart 对象作为邮件内容并保存
    message.setContent(allPart);
    message.saveChanges();
    return message;
  }

  public void baseSendMail(MailRecipient info) throws MessagingException, Exception {
    Transport.send(setMessageInfo(info));
  }

  public List<String[]> baseSendMail(List<MailRecipient> infoList) {
    List<String[]> list = new ArrayList<>();
    for (MailRecipient info : infoList) {
      String[] res = new String[2];
      try {
        baseSendMail(info);
        res[0] = info.getToAddress();
      } catch (MessagingException e) {
        res[1] = e.getMessage();
        e.printStackTrace();
      } catch (Exception e) {
        res[1] = e.getMessage();
        e.printStackTrace();
      }
      list.add(res);
    }
    return list;
  }

  public List<Message> setMessageInfoList(List<MailRecipient> infoList) throws Exception {
    List<Message> messageList = new ArrayList<>();
    for (int i = 0; i < infoList.size(); i++) {
      messageList.add(setMessageInfo(infoList.get(i)));
    }
    return messageList;
  }
  /** 创建附件 */
  private MimeBodyPart createAttachment(File file) throws Exception {
    MimeBodyPart attachmentPart = new MimeBodyPart();
    FileDataSource fds = new FileDataSource(file);
    attachmentPart.setDataHandler(new DataHandler(fds));
    attachmentPart.setFileName(MimeUtility.encodeText(fds.getName()));
    return attachmentPart;
  }

  /** 根据传入的邮件正文body和文件路径创建图文正文部分 */
  private MimeBodyPart createContent(MailRecipient info) throws Exception {
    // 用于保存最终正文部分
    MimeBodyPart contentBody = new MimeBodyPart();
    // 用于组合文本和图片，"related"型的MimeMultipart对象
    MimeMultipart contentMulti = new MimeMultipart("related");

    // 正文的文本部分
    MimeBodyPart textBody = new MimeBodyPart();
    textBody.setContent(info.getContent(), "text/html;charset=utf-8");
    contentMulti.addBodyPart(textBody);

    // 正文的图片部分
    MimeBodyPart jpgBody = new MimeBodyPart();
    FileDataSource fds = new FileDataSource(info.getContentImage());
    jpgBody.setDataHandler(new DataHandler(fds));
    // jpgBody.setFileName(fds.getName());没有设置正文图片名字则不会在正文中显示该图片并且会变成附件中后缀名为.bin的该正文图片文件
    jpgBody.setFileName(fds.getName());
    jpgBody.setContentID(info.getContentImageID());
    contentMulti.addBodyPart(jpgBody);

    // 将上面"related"型的 MimeMultipart 对象作为邮件的正文
    contentBody.setContent(contentMulti);
    return contentBody;
  }


  private String readTemplet(String templetPath) throws IOException {
    InputStream input = null;
    InputStreamReader read = null;
    BufferedReader reader = null;

    if (!new File(templetPath).exists()) {
      return "";
    }
    try {
      input = new FileInputStream(templetPath);
      read = new InputStreamReader(input, "UTF-8");
      reader = new BufferedReader(read);
      String line;
      String result = "";
      while ((line = reader.readLine()) != null) {
        result += line + "\n";
      }
      return result.substring(result.indexOf("<html>"));
    } catch (Exception e) {
      e.printStackTrace();
      return "";
    } finally {
      reader.close();
      read.close();
      input.close();
    }
  }

  //  @Override
  //  public void run() {
  //    for (int i = 0; i < messageList.size(); i++) {
  //      try {
  //        Transport.send(messageList.get(i));
  //      } catch (MessagingException e) {
  //        e.printStackTrace();
  //      }
  //    }
  //  }

  public Boolean sendEmail(MailRecipient info) {
    Boolean result = false;
    try {
      Properties properties = new Properties();
      Session session = Session.getInstance(properties, null);
      properties.put("mail.smtp.host", mailSender.getHost());
      properties.put("mail.smtp.auth", mailSender.getAuth()); // smtp校验
      Transport transport = session.getTransport("smtp");
      transport.connect(mailSender.getHost(), mailSender.getForm(), mailSender.getFormPassword());
      Message message = new MimeMessage(session);

      message.setSubject(info.getSubject());
      message.setReplyTo(InternetAddress.parse(mailSender.getReplayAddress()));
      message.setFrom(new InternetAddress(properties.getProperty("mail.smtp.user"), "WSF"));
      message.setRecipient(RecipientType.TO, new InternetAddress(info.getToAddress()));
      // 创建邮件的各个 MimeBodyPart 部分
      // 将邮件中各个部分组合到一个"mixed"型的 MimeMultipart 对象
      MimeMultipart allPart = new MimeMultipart("mixed");
      if (info.getMailAttachments() != null && info.getMailAttachments().length > 0) {
        for (File file : info.getMailAttachments()) {
          allPart.addBodyPart(createAttachment(file));
        }
      }

      MimeBodyPart content = createContent(info);
      allPart.addBodyPart(content);

      // 将上面混合型的 MimeMultipart 对象作为邮件内容并保存
      message.setContent(allPart);
      message.saveChanges();

      transport.sendMessage(message, message.getRecipients(Message.RecipientType.TO)); // 发送邮件
      transport.close();
      result = true;
    } catch (Exception e) {
      e.printStackTrace();
    }
    return result;
  }
}
